手把手带你在微前端(qiankun)中实现多页签功能(路由keepalive) |
您所在的位置:网站首页 › react 配置路由表 › 手把手带你在微前端(qiankun)中实现多页签功能(路由keepalive) |
效果展示
在上篇文章中已经实现了基本的多页签功能,接下来在微前端中实现多页签功能。建议没看过上一篇的朋友,可以先看下上一篇。 手把手带你基于ant design pro 5实现多tab页(路由keepalive) juejin.cn/post/722476… 实现思路实现起来很简单,还记得上篇文章中获取路由组件实例用的是useOutlet这个hooks,本篇我们只需要自己实现一下这个方法就能实现微前端的多页签了。 具体实现 初始化微前端项目 创建pnpm workspace项目不了解pnpm workspace的可以从网上先了解一下,首先我们先建一个目录,并进入 mkdir antd-pro-qiankun-keepalive-tabs && cd antd-pro-qiankun-keepalive-tabs 复制代码执行下面命令,初始化项目 pnpm init 复制代码在根目录新建pnpm-workspace.yaml文件,并写入以下代码 packages: - "modules/*" 复制代码在根目录下新建modules目录,我们微前端模块放在里面 mkdir modules 复制代码进入modules文件夹,使用antd pro脚手架初始化微前端主项目,选umi4 cd modules && pro create main 复制代码在modules文件夹下创建app1文件夹,然后执行以下命令 cd app1 && pnpm create umi 复制代码选择Simple App 使用pnpm
我们在app1根目录下创建.env文件,更改启动端口
再回到项目根目录下,更改package.json文件,增加一个start命令 "start": "pnpm -C ./modules/main start & pnpm -C ./modules/app1 start" 复制代码
启动成功后,访问http://localhost:8000 和 http://localhost:8001, 此时应该能正常访问。 使用qiankun微前端插件在主项目modules/main/config/config.ts配置文件中使用qiankun插件,具体qiankun用法请参考官网 qiankun: { master: { apps: [{ name: 'app1', entry: '//localhost:8001' }], } }, 复制代码更改app1目录下package.json中name字段,改成app1 给app1模块安装umi插件,执行以下命令 pnpm --filter "app1" add @umijs/plugins 复制代码安装完依赖后,在modules/app1/.umirc.ts配置文件中使用qiankun插件 plugins: ['@umijs/plugins/dist/qiankun'], qiankun: { slave: {}, }, 复制代码
回到根目录执行npm start命令,启动项目。启动成功后,访问http:localhost:8000 登录成功后,点击app1-index菜单,就能看到app1模块 src/pages/index.tsx里的内容了。
把上一篇文章中src/layouts文件夹和文件一起复制到当前主项目src目录下
把路由中的microApp属性移除,因为使用了MicroAppWithMemoHistory这种加载方式,具体请参考qiankun官网。再添加一个app1 docs路由测试,更改重定向路由到/app1/ 修改主项目qiankun配置,关闭微前端单例模式,如果开启单例,就没办法保留其他tab的状态了。把singular设置为false qiankun: { master: { apps: [{ name: 'app1', entry: '//localhost:8001' }], singular: false, }, }, 复制代码移除app1模块/src/layouts文件夹,并在路由中移除,移除后有可能会报错,重启一下服务就行了。 更改app1模块中src/pages/index.tsx文件,添加一个input组件,测试切换路由是否能保持状态,并且给div设置一个很大的高度,测试是否能保留滚动条位置。
现在是不支持主项目路由的,切换到“欢迎”菜单会报错,我们兼容一下主项目路由。
把主项目qiankun配置抽到一个单独的文件中导出,方便我们在代码中获取有哪些子模块。然后再主项目app.ts文件中引入qiankun配置,然后再导出。 删除config文件中的qiankun apps和singular配置
在主项目src目录下新建qiankun-config.ts文件,代码如下 export const qiankunConfig = { master: { apps: [{ name: 'app1', entry: '//localhost:8001' }], singular: false, }, }; 复制代码在src/app.ts文件中赋值给qiankun,并导出qiankun。
更改useOutlet.tsx文件 import { MicroAppWithMemoHistory, useLocation, useOutlet as useChildren } from '@umijs/max' import { qiankunConfig } from '@/qiankun-config'; export function useOutlet() { const { pathname } = useLocation(); const children = useChildren(); const [, moduleName] = pathname.split('/'); // 如果没有匹配到子模块,就使用主模块的useOutlet if (!qiankunConfig.apps.some(app => app.name === moduleName)) { return children; } return ( ) } 复制代码主模块的路由也支持了 实现思路:通过父子模块通信,把这几个方法传到子模块中 改造/src/layouts/indes.tsx文件,把这几个方法传给子模块。我以为上面东西搞完,基本就结束了,谁知道在测试的时候发现了个大bug。bug流程是这样的,a切换到b,关掉a,再打开a就会一直空白。然后报这个错:dex.js:1 single-spa minified message #31: See https://single-spa.js.org/error/?code=31&arg=mount&arg=parcel&arg=app1_1&arg=3000我到qiankun仓库issue找相关解决方案,发现也有人遇到这个问题,但是没有明确的解决方案,然后自己扒qiankun源码看,最后发现了bug的原因。原来qiankun在加载子模块生命周期的时候,会做缓存,缓存的key用的微前端容器的xpath路径,我先打开一个,然后在打开一个,然后关掉第一个,然后再打开第一个,这时候新加的xpath和前面一个一样了,然后qiankun发现当前xpath已经加载了,就不再去加载。这个bug大致是这样触发的,我们只需要把缓存的key改成当前url + xpath就行了,这个我后面会单独出一篇文章去讲,这块逻辑有点复杂。 bug演示 然后我就把umi-qiankun插件引入到当前主项目中,改了点源码,后面会给umi提个pr,作者可能不会合并,因为这种使用场景不多。
复制app1整个文件夹内容到app2文件夹下,改.env的启动端口为8002,然后主项目配置一下路由和微前端配置。 效果展示 我这个实现方案应该会有性能问题,最好的方案应该在子模块中实现缓存,同一个模块不用每次都重新加载,性能应该会好一点。大家有更好的方案可以在评论区提醒我一下。 后面我会把这个功能做成umi插件,方便大家使用,接下来应该会出一篇umi插件开发的文章教程,对这个感兴趣的可以关注我一下。 文中的代码我已经上传到github了,地址是:github.com/dbfu/antd-p… |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |